// API请求工具类
import common from '@/utils/common.js';

// 使用实际的服务器IP地址
const BASE_URL = 'http://localhost:1750/api'; // 后端API地址
const TIMEOUT = 60000; // 请求超时时间设置为60秒，增加到更合理的值

// 保存BASE_URL到本地存储，供WebSocket使用
uni.setStorageSync('baseUrl', BASE_URL.replace('/api', ''));

// 是否正在刷新token的标记
let isRefreshing = false;
// 重试队列，每一项将是一个待执行的函数形式
let requests = [];

// 解析JWT token获取过期时间
const parseJwt = (token) => {
    try {
        const base64Url = token.split('.')[1];
        const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
        const jsonPayload = decodeURIComponent(atob(base64).split('').map((c) => {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
        return JSON.parse(jsonPayload);
    } catch (e) {
        console.error('解析JWT失败', e);
        return null;
    }
};

// 检查token是否即将过期（提前5分钟判断）
const isTokenExpired = () => {
    const token = uni.getStorageSync('token');
    if (!token) return true;

    const payload = parseJwt(token);
    if (!payload || !payload.exp) return true;

    const currentTime = Date.now() / 1000;
    const expirationBuffer = 5 * 60; // 5分钟（秒为单位）

    return currentTime > (payload.exp - expirationBuffer);
};

// 刷新token
const refreshToken = () => {
    return new Promise((resolve, reject) => {
        const token = uni.getStorageSync('token');
        if (!token) {
            reject(new Error('没有token'));
            return;
        }

        uni.request({
            url: BASE_URL + '/auth/refresh',
            method: 'POST',
            header: {
                'Content-Type': 'application/json',
                'Authorization': token
            },
            success: (res) => {
                if (res.statusCode === 200 && res.data.code === 200) {
                    const newToken = res.data.data;
                    console.log('Token刷新成功');
                    // 更新存储的token
                    uni.setStorageSync('token', newToken);
                    resolve(newToken);
                } else {
                    // 刷新失败
                    console.error('Token刷新失败:', res);
                    uni.removeStorageSync('token');
                    uni.removeStorageSync('userInfo');
                    reject(new Error('刷新token失败'));
                }
            },
            fail: (err) => {
                // 刷新失败
                console.error('Token刷新请求失败:', err);
                uni.removeStorageSync('token');
                uni.removeStorageSync('userInfo');
                reject(err);
            }
        });
    });
};

// 请求拦截器
const request = async (options) => {
    // 检查是否需要token
    const needToken = !options.url.includes('/auth/login') && !options.url.includes('/auth/register');

    // 检查token是否即将过期，如果是且需要token，先刷新token
    const token = uni.getStorageSync('token');
    if (needToken && token && isTokenExpired() && !options.url.includes('/auth/refresh')) {
        try {
            // 如果没有其他刷新请求在进行中
            if (!isRefreshing) {
                isRefreshing = true;
                console.log('Token即将过期，尝试刷新');
                const newToken = await refreshToken();
                isRefreshing = false;

                // 执行队列中的请求
                requests.forEach(cb => cb(newToken));
                requests = [];

                // 使用新token继续当前请求
                options.header = {
                    ...options.header,
                    'Authorization': newToken
                };
            } else {
                // 如果已经有刷新请求在进行中，将当前请求加入队列
                return new Promise((resolve, reject) => {
                    requests.push(newToken => {
                        options.header = {
                            ...options.header,
                            'Authorization': newToken
                        };
                        request(options).then(resolve).catch(reject);
                    });
                });
            }
        } catch (error) {
            console.error('自动刷新token失败', error);
            isRefreshing = false;

            // 如果是登录页面，不跳转
            if (!options.url.includes('/auth/login')) {
                common.showToast('登录已过期，请重新登录', 'none');
                setTimeout(() => {
                    uni.navigateTo({
                        url: '/pages/login/login'
                    });
                }, 1500);
            }
            throw error;
        }
    }

    return new Promise((resolve, reject) => {
        const currentToken = uni.getStorageSync('token');

        uni.request({
            url: BASE_URL + options.url,
            method: options.method || 'GET',
            data: options.data || {},
            timeout: TIMEOUT,
            header: {
                'Content-Type': 'application/json',
                ...(needToken && currentToken ? { 'Authorization': currentToken } : {}),
                ...options.header
            },
            success: (res) => {
                if (res.statusCode === 200) {
                    // 后端返回的Result结构：code, msg, data
                    if (res.data.code === 200) {
                        // 成功状态码为200，表示请求成功
                        resolve(res.data);
                    } else {
                        common.showError(res.data.msg || '请求失败');
                        reject(res.data);
                    }
                } else if (res.statusCode === 401) {
                    // token过期，尝试刷新token
                    handleTokenExpired(options, resolve, reject);
                } else {
                    common.showError(`网络错误 (${res.statusCode})`);
                    reject(res);
                }
            },
            fail: (err) => {
                console.error('请求失败:', err);

                if (err.errMsg.includes('timeout')) {
                    common.showError('请求超时，请稍后再试');
                } else if (err.errMsg.includes('Failed to fetch')) {
                    common.showError('网络连接失败，请检查网络');
                } else {
                    common.showError('网络请求失败');
                }
                reject(err);
            }
        });
    });
};

// 处理token过期
const handleTokenExpired = (options, resolve, reject) => {
    // 如果是刷新token的请求，直接跳转登录页
    if (options.url.includes('/auth/refresh')) {
        uni.removeStorageSync('token');
        uni.removeStorageSync('userInfo');
        common.showToast('登录已过期，请重新登录', 'none');
        setTimeout(() => {
            uni.navigateTo({
                url: '/pages/login/login'
            });
        }, 1500);
        reject(new Error('刷新token失败'));
        return;
    }

    if (!isRefreshing) {
        isRefreshing = true;
        console.log('Token已过期，尝试刷新');

        // 直接调用刷新token接口，避免循环引用
        uni.request({
            url: BASE_URL + '/auth/refresh',
            method: 'POST',
            header: {
                'Content-Type': 'application/json',
                'Authorization': uni.getStorageSync('token')
            },
            success: (res) => {
                if (res.statusCode === 200 && res.data.code === 200) {
                    const newToken = res.data.data;
                    console.log('Token刷新成功');
                    // 更新存储的token
                    uni.setStorageSync('token', newToken);

                    // 执行队列中的请求
                    requests.forEach(cb => cb(newToken));
                    requests = [];

                    // 重新发起请求
                    request({
                        ...options,
                        header: {
                            ...options.header,
                            'Authorization': newToken
                        }
                    }).then(resolve).catch(reject);
                } else {
                    console.error('Token刷新失败:', res);
                    // 刷新失败，清除登录状态并跳转
                    uni.removeStorageSync('token');
                    uni.removeStorageSync('userInfo');
                    common.showToast('登录已过期，请重新登录', 'none');

                    // 延迟跳转，让用户能看到提示
                    setTimeout(() => {
                        uni.navigateTo({
                            url: '/pages/login/login'
                        });
                    }, 1500);
                    reject(res.data);
                }
            },
            fail: (err) => {
                console.error('Token刷新请求失败:', err);
                // 刷新失败，清除登录状态并跳转
                uni.removeStorageSync('token');
                uni.removeStorageSync('userInfo');
                common.showToast('登录已过期，请重新登录', 'none');

                // 延迟跳转，让用户能看到提示
                setTimeout(() => {
                    uni.navigateTo({
                        url: '/pages/login/login'
                    });
                }, 1500);
                reject(err);
            },
            complete: () => {
                isRefreshing = false;
            }
        });
    } else {
        // 将请求加入队列，等待刷新token完成后再重试
        return new Promise(resolvePromise => {
            requests.push(token => {
                request({
                    ...options,
                    header: {
                        ...options.header,
                        'Authorization': token
                    }
                }).then(resolve).catch(reject);
            });
        });
    }
};

// 封装常用请求方法
export const http = {
    get(url, params = {}) {
        // 过滤掉null和undefined值
        const filteredParams = {};
        Object.keys(params).forEach(key => {
            if (params[key] !== null && params[key] !== undefined) {
                filteredParams[key] = params[key];
            }
        });

        // 如果有参数，构建查询字符串
        let queryString = '';
        if (Object.keys(filteredParams).length > 0) {
            queryString = '?' + Object.keys(filteredParams)
                .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(filteredParams[key])}`)
                .join('&');
        }

        return request({
            url: url + queryString,
            method: 'GET'
        });
    },

    post(url, data = {}, options = {}) {
        // 处理URL参数
        let finalUrl = url;
        if (options.params) {
            const queryString = Object.keys(options.params)
                .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(options.params[key])}`)
                .join('&');
            finalUrl = url + (queryString ? `?${queryString}` : '');
        }

        return request({
            url: finalUrl,
            method: 'POST',
            data
        });
    },

    put(url, data = {}, options = {}) {
        // 处理URL参数
        let finalUrl = url;
        if (options.params) {
            const queryString = Object.keys(options.params)
                .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(options.params[key])}`)
                .join('&');
            finalUrl = url + (queryString ? `?${queryString}` : '');
        }

        return request({
            url: finalUrl,
            method: 'PUT',
            data
        });
    },

    delete(url, options = {}) {
        // 处理URL参数
        let finalUrl = url;
        if (options.params) {
            const queryString = Object.keys(options.params)
                .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(options.params[key])}`)
                .join('&');
            finalUrl = url + (queryString ? `?${queryString}` : '');
        }

        return request({
            url: finalUrl,
            method: 'DELETE'
        });
    }
};

// 在App启动时检查token，如果即将过期则刷新
export const checkAndRefreshToken = async () => {
    if (isTokenExpired()) {
        try {
            console.log('App启动时检查到token即将过期，尝试刷新');
            await refreshToken();
            console.log('Token已自动刷新');
            return true;
        } catch (error) {
            console.error('Token刷新失败', error);
            return false;
        }
    }
    return true;
};

export default http; 